package main

import (
	"context"
	"flag"
	libLog "log"
	"net"
	"os"

	"github.com/libp2p/go-libp2p"
	"github.com/libp2p/go-libp2p-core/network"
)

var (
	log        = libLog.New(os.Stderr, "", libLog.Llongfile)
	listenAddr string
)

func init() {
	flag.StringVar(&listenAddr, "l", ":22333", "-l <ip:port>")
	flag.Parse()
}

func main() {
	// new libp2p host
	h, err := libp2p.New(context.Background())
	if err != nil {
		log.Panic(err)
	}
	defer h.Close()

	log.Println(h.Addrs(), h.ID())
	addr := h.Addrs()[0].String()
	addr += "/p2p/"
	addr += h.ID().Pretty()
	log.Println(addr)

	// open a tcp port to listen incomming data
	tcpListener, err := net.Listen("tcp4", listenAddr)
	if err != nil {
		log.Panic(err)
	}
	defer tcpListener.Close()

	h.SetStreamHandler("pf.nealfree.cf", func(stream network.Stream) {
		for {
			// accept
			conn, err := tcpListener.Accept()
			if err != nil {
				log.Println(err)
				break
			}

			// send a msg to start a forward session
			_, err = stream.Write([]byte("accept"))
			if err != nil {
				log.Println(err)
				break
			}

			//tx
			txBuffer := make([]byte, 1<<20)
			go func() {
				for {
					n, err := conn.Read(txBuffer)
					if err != nil || n == 0 {
						log.Println(err)
						stream.Reset()
						break
					}

					_, err = stream.Write(txBuffer[:n])
					if err != nil {
						log.Println(err)
						stream.Reset()
						break
					}
				}
			}()
			//rx
			rxBuffer := make([]byte, 1<<20)
			go func() {
				for {
					n, err := stream.Read(rxBuffer)
					if err != nil || n == 0 {
						log.Println("socket closed")
						stream.Reset()
						break
					}

					_, err = conn.Write(rxBuffer[:n])
					if err != nil || n == 0 {
						log.Println(err)
						stream.Reset()
						break
					}
				}
			}()
		} // access loop
	})

	select {}
}
